package coreModelTests;


import static org.junit.Assert.*;

import hitExceptions.InvalidDataException;
import hitExceptions.InvalidOperationException;

import java.util.*;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import coreModel.*;



public class ProductTest {

	public static List<Product> productList;
	public static List <Barcode> barcodeList;
	static int SIZE=20;
	static ProductContainer tmpContainer1;
	static ProductContainer tmpContainer2;
	static ProductContainer rootSU;
	static 	ProductContainer tmpCont;
	@BeforeClass
	public static void setUpBeforeClass() throws Exception
	{
		try
		{
			productList = new ArrayList<Product>();
			barcodeList= new ArrayList<Barcode>();
			for(int x=0; x<SIZE; x++)
			{
				String description= "product "+x;
				Barcode tmpBarcode= new Barcode();
				Product tmpProduct= new Product(tmpBarcode, description, x, x, new Supply());
				productList.add(tmpProduct);
				barcodeList.add(tmpBarcode);
			}
			float size=10;
			rootSU= new StorageUnit("root");
			// product Group 1
			tmpContainer1= new ProductGroup("Group 1",rootSU, new Supply(size,Unit.COUNT));

			// product Group 2
			tmpContainer2= new ProductGroup("Group 2",rootSU, new Supply(size,Unit.GALLONS));


			tmpCont = new ProductGroup("tester",rootSU,new Supply());

			//puts half my products in on group
			for(int x=0;x<SIZE/2;x++)
			{
				tmpContainer1.addProduct(productList.get(x));
			}

			//puts half in other group
			for(int x=SIZE/2;x<SIZE;x++)
			{
				tmpContainer2.addProduct(productList.get(x));
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}

	@Before
	public void setUp() throws Exception
	{
	}

	@Test
	public void testGetCreationDate()
	{

		try
		{
			Date now = new Date();
			Product p= new Product("name",new Barcode());
			assertNotSame(now,p.getCreationDate());
			p.setCreationDate(now);
			assertEquals(now,p.getCreationDate());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}

	}

	@Test
	public void testSetCreationDate()
	{
		try
		{
			Date now = new Date();
			Product p= new Product("name", new Barcode());
			assertNotNull(p.getCreationDate());
			assertNotSame(now,p.getCreationDate());
			p.setCreationDate(now);
			assertEquals(now,p.getCreationDate());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}

	@Test
	public void testGetBarcode()
	{
		for(int x=0;x<SIZE;x++)
		{
			assertEquals(barcodeList.get(x),productList.get(x).getBarcode());
		}
	}

	@Test
	public void testSetBarcode()
	{
		try
		{
			Barcode b= new Barcode();
			Product p = new Product("name",new Barcode());
			assertNotSame(b, p.getBarcode());
			assertNotNull(p.getBarcode());
			p.setBarcode(b);
			assertEquals(b, p.getBarcode());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}

	@Test
	public void testGetDescription()
	{ 
		int x=0;
		for( Product p :productList)
		{
			String str="product "+x;
			assertEquals(str, p.getDescription());
			x++;
		}
	}

	@Test
	public void testSetDescription()
	{
		try{
			int x=SIZE;
			for( Product p :productList)
			{
				String str="product "+x;
				assertNotSame(str, p.getDescription());
				p.setDescription(str);
				x--;
			}

			x=SIZE;
			for( Product p :productList)
			{
				String str="product "+x;
				assertEquals(str, p.getDescription());
				x--;
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}


	}

	@Test
	public void testGetSize()
	{
		for( Product p :productList)
		{
			assertTrue(0==p.getSize());
		}

	}

	@Test
	public void testSetSize()
	{
		try
		{
			Product p = new Product("name",new Barcode());
			assertTrue(p.getSize()==0);
			float size= 10;
			try
			{
				p.setSize(size);
			} 
			catch (InvalidDataException e)
			{

				e.printStackTrace();
				fail("Should have thrown an exception");
			}
			assertTrue(p.getSize()==size);
			assertNotNull(p.getSize());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}

	}

	@Test
	public void testSetUnit()
	{
		try
		{
			Product p = new Product("name",new Barcode());
			assertNull(p.getUnit());
			p.setUnit(Unit.COUNT);
			assertEquals(Unit.COUNT,p.getUnit());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}

	@Test
	public void testGetUnit()
	{
		try
		{
			Product p = new Product("name",new Barcode());
			assertNull(p.getUnit());
			p.setUnit(Unit.COUNT);
			assertEquals(Unit.COUNT,p.getUnit());
			p.setUnit(Unit.FLUID_OUNCES);
			assertEquals(Unit.FLUID_OUNCES,p.getUnit());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}

	@Test
	public void testGetUnitAsString()
	{
		try
		{
			Product p = new Product("name",new Barcode());
			assertNull(p.getUnit());
			p.setUnit(Unit.COUNT);
			assertEquals("COUNT",p.getUnitAsString());
			p.setUnit(Unit.FLUID_OUNCES);
			assertEquals("FLUID_OUNCES",p.getUnitAsString());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}

	@Test
	public void testGetShelfLife()
	{
		int x=0;
		for( Product p : productList)
		{
			assertEquals(x,p.getShelfLife());
			x++;
		}
	}

	@Test
	public void testSetShelfLife()
	{
		try
		{
			int x=SIZE*-1;
			for( Product p : productList)
			{
				boolean test=false;
				try
				{
					p.setShelfLife(x);
				} 
				catch (InvalidDataException e)
				{
					test=true;
					// TODO Auto-generated catch block
				}
				if(!test)
				{
					fail("didn't throw the error");
				}


			}
			Product p = new Product("name",new Barcode());

			p.setShelfLife(15);

			assertEquals(15,p.getShelfLife());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}

	@Test
	public void testGetThreeMonthSupply()
	{
		try
		{
			int x=0;
			for( Product p : productList)
			{
				assertEquals(x,p.getThreeMonthSupply());
				x++;
			}
			Product product= new Product("name",new Barcode());

			product.setThreeMonthSupply(10);
			assertEquals(product.getThreeMonthSupply(),10);
			product.setThreeMonthSupply(0);
			assertEquals(product.getThreeMonthSupply(),0);
			product.setThreeMonthSupply(1);
			assertEquals(product.getThreeMonthSupply(),1);

		}
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}

	}

	@Test
	public void testSetThreeMonthSupply()
	{
		int x=SIZE*-1;
		for( Product p : productList)
		{
			boolean test=false;
			try
			{
				p.setThreeMonthSupply(x);
			} 
			catch (InvalidDataException e)
			{
				test=true;
				// TODO Auto-generated catch block

			}
			if(!test)
			{
				fail("didn't throw the error");
			}


		}
		try
		{
			Product p = new Product("name",new Barcode());

			p.setThreeMonthSupply(15);
			assertEquals(15,p.getThreeMonthSupply());

		} 
		catch (Exception e)
		{
			e.printStackTrace();
			fail();
		}

	}

	@Test
	public void testGetContainers()
	{
		try
		{
			Collection<ProductContainer> answerCont1= new ArrayList<ProductContainer>();
			answerCont1.add(tmpContainer1);
			Collection<ProductContainer> answerCont2= new ArrayList<ProductContainer>();
			answerCont2.add(tmpContainer2);

			Product p= new Product("name",new Barcode());

			assertNull(p.getContainers());
			for(int x=0;x<SIZE/2;x++)
			{
				assertArrayEquals(productList.get(x).getContainers().toArray(),answerCont1.toArray());
				assertNotSame(productList.get(x).getContainers(),answerCont1);
			}

			for(int x=SIZE/2;x<SIZE;x++)
			{
				assertArrayEquals(productList.get(x).getContainers().toArray(),answerCont2.toArray());
				assertNotSame(productList.get(x).getContainers(),answerCont2);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}

	@Test
	public void testAddContainerToProdcutList()
	{
		try
		{
			Collection<ProductContainer> answerCont1= new ArrayList<ProductContainer>();
			answerCont1.add(tmpContainer1);
			answerCont1.add(tmpCont);
			Collection<ProductContainer> answerCont2= new ArrayList<ProductContainer>();
			answerCont2.add(tmpContainer2);
			answerCont2.add(tmpCont);

			Product p= new Product("name",new Barcode());

			assertNull(p.getContainers());
			for(int x=0;x<SIZE/2;x++)
			{
				productList.get(x).addContainerToProdcutList(tmpCont);
				assertArrayEquals(productList.get(x).getContainers().toArray(),answerCont1.toArray());
				assertNotSame(productList.get(x).getContainers(),answerCont1);
			}

			for(int x=SIZE/2;x<SIZE;x++)
			{
				productList.get(x).addContainerToProdcutList(tmpCont);
				assertArrayEquals(productList.get(x).getContainers().toArray(),answerCont2.toArray());
				assertNotSame(productList.get(x).getContainers(),answerCont2);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
			fail();
		}
	}


	@Test
	public void testRemoveContainerFromProductList() 
	{
		Collection<ProductContainer> answerCont1= new ArrayList<ProductContainer>();
		answerCont1.add(tmpContainer1);
		//answerCont1.add(tmpCont);
		Collection<ProductContainer> answerCont2= new ArrayList<ProductContainer>();
		answerCont2.add(tmpContainer2);
		//answerCont2.add(tmpCont);

		for(int x=0;x<SIZE/2;x++)
		{
			try
			{
				productList.get(x).removeContainerFromProductList(tmpCont);
			} 
			catch (InvalidOperationException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
				fail();
			}
			assertArrayEquals(productList.get(x).getContainers().toArray(),answerCont1.toArray());
			assertNotSame(productList.get(x).getContainers(),answerCont1);
		}

		for(int x=SIZE/2;x<SIZE;x++)
		{
			try
			{
				productList.get(x).removeContainerFromProductList(tmpCont);
			} catch (InvalidOperationException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			assertArrayEquals(productList.get(x).getContainers().toArray(),answerCont2.toArray());
			assertNotSame(productList.get(x).getContainers(),answerCont2);
		}
	}

	@Test
	public void testMoveProduct()
	{
		//fail("Not yet implemented");
	}

}
